﻿/* *****************************************************************************
 * @ Encoding: UTF-8
 * @ File Name: naughty_differential_node_base.hpp
 * @ Author: cal
 * @ Email: naughtygeng@qq.com
 * @ Created Time: 2022-Jul-06(Wednesday) 11:31:04
 * @ All Rights Reserved
 * *****************************************************************************/

#ifndef NAUGHTY_DIFFERENTIAL_NODE_BASE_HPP
#define NAUGHTY_DIFFERENTIAL_NODE_BASE_HPP

#include <stdint.h>
#include <memory>
#include <vector>
#include <string>
#include <utility>
#include <map>
#include <cassert>
#include <cmath>

namespace naughty_differential
{

enum node_type
{
	node_type_val,
	node_type_num,

	node_type_add,
	node_type_sub,
	node_type_mul,
	node_type_div,
	node_type_sin,
	node_type_cos,
	node_type_tan,
	node_type_log,
	node_type_ln,
	node_type_pow,
	node_type_exp,
};

class node_base
{

private:

	mutable std::vector<std::shared_ptr< node_base>> m_parameters;

public:

	node_base(std::vector<std::shared_ptr<node_base>> params)
	{
		for (std::shared_ptr<node_base> param_ptr : params)
		{
			m_parameters.push_back(param_ptr->clone());
		}
	}

	virtual enum node_type get_node_type() = 0;

	virtual std::shared_ptr<node_base> differential(std::string variable /* = 'x' */ ) = 0;

	virtual std::string serialize() = 0;

	virtual std::string to_string() const = 0;

	virtual std::shared_ptr<node_base> clone() = 0;

	virtual double get_value(std::map<std::string, double> val_value_map) = 0;

	virtual std::string identity_string() const = 0;

	std::vector<std::shared_ptr<node_base>> parameters_clone()
	{
		std::vector<std::shared_ptr<node_base>> cloned_params;

		for (std::shared_ptr<node_base> param : m_parameters)
		{
			cloned_params.push_back(param->clone());
		}

		return cloned_params;
	}

	std::vector<double> get_params_value(std::map<std::string, double> val_value_map)
	{
		std::vector<double> result;
		for (std::shared_ptr<node_base> param : m_parameters)
		{
			result.push_back(param->get_value(val_value_map));
		}
		return result;
	}

	std::vector<std::shared_ptr<node_base>>& get_parameters() const {return m_parameters;}

};

}

#endif
